Android — TextInputLayout

前言

最近看到一个蛮实用的 “效果” ,一图胜前言:(刷新页面重新看)

我以为作者写的呢,今天无意试了一下Android Studio 内置登录页面,运行一看,哇,效果一模一样,最后发现是 Android 特喵的有这么一个控件。。。控件。。。可能是我过于挑剔吧,看着还是有点丑陋,只是一个 hint 上移的动画感觉很一般。深入了解一下,emmmm,发现这个控件不简单,可以做到一下几点:

  1. 自定义样式,拒绝原本简单丑陋的动画
  2. 实时错误检查,并自定义错误提示

实现效果如下:

当有错误的时候,把 Button 设置为不可点击。感觉效果不错,实用性也很强。那么,下面就记录记录一下这个控件的使用。

首先

添加依赖:

1
implementation 'com.android.support:design:26.1.0'

介绍这个控件的几个属性:

1
app:errorEnabled="true" //开启错误提示
1
app:counterEnabled="true" //开启计数
1
app:counterTextAppearance="@style/CounterText" //为计数字体设置样式
1
app:counterOverflowTextAppearance="@style/CounterTextError" //当数字超出时的字体样式
1
app:counterMaxLength="8" //设置最大长度
1
app:hintTextAppearance="@style/InputHint" //设置 hint 文本的样式

布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context="top.omooo.testlogin.MainActivity">
<android.support.design.widget.TextInputLayout
android:id="@+id/inputLayoutUsername"
app:errorEnabled="true"
app:counterEnabled="true"
app:counterTextAppearance="@style/CounterText"
app:counterOverflowTextAppearance="@style/CounterTextError"
app:counterMaxLength="8"
android:layout_marginTop="8dp"
app:hintTextAppearance="@style/InputHint"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_username"
android:hint="用户名"
android:textColor="@color/inputHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/inputLayoutPassword"
app:errorEnabled="true"
app:counterEnabled="true"
app:counterTextAppearance="@style/CounterText"
app:counterOverflowTextAppearance="@style/CounterTextError"
app:counterMaxLength="16"
app:hintTextAppearance="@style/InputHint"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_password"
android:hint="密码"
android:textColor="@color/inputHint"
android:inputType="textPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/btn_login"
android:text="登录"
android:textSize="20sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

样式:

1
2
3
4
5
6
7
8
9
10
11
12
<style name="InputHint">
<item name="android:textColor">#0099CC</item>
<item name="android:textSize">15sp</item>
</style>
<style name="CounterText">
<item name="android:textColor">#0099CC</item>
<item name="android:textSize">15sp</item>
</style>
<style name="CounterTextError">
<item name="android:textColor">#FF6666</item>
<item name="android:textSize">20sp</item>
</style>

用到的颜色值:

1
<color name="inputHint">#0099CC</color>

处理错误信息

这里需要监听 EditText 的文本变化,所以需要实现 TextWatcher 的接口,重写三个方法。对了,这里说明一下,TextInputLayout 实际上是一个容器,里面只能放一个 EditText 控件。如果我们要获取这个 EditText 的实例并设置监听的话,其实很简单:

1
mInputLayout.getEditText().addTextChangedListener(this);

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package top.omooo.testlogin;
import android.os.Bundle;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements TextWatcher{
private TextInputLayout mInputLayoutUsername;
private TextInputLayout mInputLayoutPwd;
private Button mButtonLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mInputLayoutUsername = findViewById(R.id.inputLayoutUsername);
mInputLayoutPwd = findViewById(R.id.inputLayoutPassword);
mButtonLogin = findViewById(R.id.btn_login);
mButtonLogin.setClickable(false);
//开启监听
mInputLayoutUsername.getEditText().addTextChangedListener(this);
mInputLayoutPwd.getEditText().addTextChangedListener(this);
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
boolean hasErrorUsername;
boolean hasErrorPwd;
int counter = mInputLayoutUsername.getEditText().getText().toString().length();
if (counter < 4) {
mInputLayoutUsername.setErrorEnabled(true);
mInputLayoutUsername.setError("用户名不能低于四位");
hasErrorUsername = true;
} else if (counter > 8) {
mInputLayoutUsername.setErrorEnabled(true);
mInputLayoutUsername.setError("用户名不能大于八位");
hasErrorUsername = true;
}else {
mInputLayoutUsername.setErrorEnabled(false);
hasErrorUsername = false;
}
int counter1 = mInputLayoutPwd.getEditText().getText().toString().length();
if (counter1 < 6) {
mInputLayoutPwd.setErrorEnabled(true);
mInputLayoutPwd.setError("密码不能低于六位");
hasErrorPwd = true;
} else if (counter1 > 16) {
mInputLayoutPwd.setErrorEnabled(true);
mInputLayoutPwd.setError("密码不能大于十六位");
hasErrorPwd = true;
}else {
mInputLayoutPwd.setErrorEnabled(false);
hasErrorPwd = false;
}
if (hasErrorPwd||hasErrorUsername) {
mButtonLogin.setClickable(false);
} else {
mButtonLogin.setClickable(true);
}
}
}
我们一直都向往,面朝大海,春暖花开。 但是几人能做到,心中有爱,四季不败?